<?php

/**
 * Created by PhpStorm.
 * User: GadflyBSD
 * Date: 16/6/30
 * Time: 15:49
 */
class ServiceAction extends Action{
	public function phpinfo(){
		phpinfo();
	}

	/**
	 * angularJS的Ajax处理方法
	 * @param   ac          请求参数ac用于指定处理数据的控制器方法, 不指定时采用angularAjax方法处理
	 * @param   mo          请求参数mo用于指定处理数据的模型名称, 不指定时采用与当前Module同名的模型
	 * @param   op          请求参数op用于当采用angularAjax方法处理时指定处理数据模型的方法名称; 或者当采用当前控制器的指定方法处理数据时作为其中一个参数
	 * @param   rsa         前端提供过来经过RSA加密的数据(客户端公钥加密,服务器端私钥解密), 未指定则使用明文方式接收所传递过来的数据
	 * @param   return_rsa  服务器端的返回结果是否对数据体部分进行加密返回(服务器端私钥加密, 客户端公钥解密)
	 */
	public function angular(){
		$this->defaultHeader($_SERVER['REQUEST_METHOD']);
		switch($_SERVER['REQUEST_METHOD']){
			case 'POST':
				$param = json_decode(file_get_contents('php://input'),true);
				break;
			case 'GET':
				$param = I('get.');
				break;
		}
		$module = ($param['ac'])?$param['ac'].'Ajax':'angular';
		$model = ($param['mo'])?ucfirst($param['mo']):ucfirst(MODULE_NAME);
		$key = session('rsa_key');
		if($param['rsa']){
			$decrypt = json_decode($this->_privateKeyDecode($param['rsa'], $key['service']['private']), true);
			$param = array_merge(array('op' => $param['op'], 'return_rsa' => $param['return_rsa']), $decrypt);
		}
		if($module == 'angular'){
			if(method_exists(D($model), $param['op']))
				$return = call_user_func(array(D($model), $param['op']), $param);
			else
				$return = array('errcode' => 10001, 'msg' => '系统在'.$model.'模型中没有找到'.$param['op'].'方法');
		}else{
			if(method_exists($this, $module))
				$return = call_user_func(array(&$this, $module), $param);
			else
				$return = array('errcode' => 10001, 'msg' => '系统在'.$model.'控制器中没有找到'.$module.'方法');
		}
		if(is_array($return)){
			if($return['data'] && $param['return_rsa']){
				$return['rsa'] = $this->_publicKeyEncode(json_encode_plus($return['data']), $key['angular']['public']);
				unset($return['data']);
			}
			$this->ajax($return);
		}else{
			echo $return;
		}
	}

	public function getBaseDataAjax($post){
		if($post['refresh']) session('rsa_key', null);
		$key = $this->_createOpensslKey();
		if(session('?userInfo')){
			$userState = array('errcode' => 0, 'content' => '用户已经登录!');
			$userInfo = session('userinfo');
		}else{
			$userState = array('errcode' => 70000, 'content' => '用户尚未登录!');
			$userInfo = NULL;
		}
		return array('errcode' => 0, 'rsa_key' => $key['angular'], 'userState' => $userState, 'userInfo' => $userInfo);
	}

	protected function loginAjax($param){
		return array('errcode' => 0, 'data' => $param);
	}

	public function verifyImg(){
		import('ORG.Util.Image');
		if(IS_AJAX && IS_POST){
			header('Content-Type: application/json; charset=utf8');
			if(session('verify') == md5($_POST['vdcode']))
				echo 'true';
			else
				echo 'false';
		}else{
			ob_end_clean();
			Image::buildImageVerify(5, 1);
		}
	}

	protected function sendSms($post, $param='WKSHOP'){
		Vendor('CtcSms');
		$sms = new CtcSms();
		$info = session(strtolower($param));
		return $sms->send($post['mobile'], $info['sideInfo']['uid'], $post['action']);
	}

	/**
	 * 生成并在页面输出显示二维码
	 * @param $url
	 */
	public function qrcode(){
		vendor("phpqrcode.phpqrcode");
		QRcode::png(urldecode(I('get.s')), false, 'L', 10, 1);
	}

	/**
	 * Ajax方式返回数据到客户端
	 * @access protected
	 * @param mixed $data 要返回的数据
	 * @param String $type AJAX返回数据格式
	 * @param Bool  $log    是否在服务器上记录LOG
	 * @param bool  $isMsg
	 *
	 * @return void
	 */
	public function ajax($param, $type='', $isMsg=true) {
		if(empty($type)) $type  =   C('DEFAULT_AJAX_RETURN');
		switch (strtoupper($type)){
			case 'JSON' :
				// 返回JSON数据格式到客户端 包含状态信息
				header('Content-Type:application/json; charset=utf-8');
				if($isMsg)
					exit(json_encode_plus($this->returnMsg($param)));
				else
					exit(json_encode_plus($param));
			case 'XML'  :
				// 返回xml格式数据
				header('Content-Type:text/xml; charset=utf-8');
				if($isMsg)
					exit(xml_encode($this->returnMsg($param)));
				else
					exit(xml_encode($param));
			case 'JSONP':
				// 返回JSON数据格式到客户端 包含状态信息
				header('Content-Type:application/json; charset=utf-8');
				$handler  =   isset($_GET[C('VAR_JSONP_HANDLER')]) ? $_GET[C('VAR_JSONP_HANDLER')] : C('DEFAULT_JSONP_HANDLER');
				if($isMsg)
					exit($handler.'('.json_encode_plus($this->returnMsg($param)).');');
				else
					exit($handler.'('.json_encode_plus($param).');');
			case 'EVAL' :
				// 返回可执行的js脚本
				header('Content-Type:text/html; charset=utf-8');
				if($isMsg)
					exit($this->returnMsg($param));
				else
					exit($param);
			case 'ARRAY':
				// 返回PHP数组或对象
				header('Content-Type:text/html; charset=utf-8');
				if($isMsg)
					exit(dump($this->returnMsg($param)));
				else
					exit(dump($param));
			default     :
				// 用于扩展其他返回格式数据
				if($isMsg)
					tag('ajax_return', $this->returnMsg($param));
				else
					tag('ajax_return', $param);
		}
	}

	protected function returnMsg($param){
		if(isset($param['errcode'])){
			$msg = ($this->cache['message'][$param['errcode']])?$this->cache['message'][$param['errcode']]:'未知的相关操作提示信息';
			$param['msg'] = ($param['msg'])?$param['msg']:$msg;
			$return = array(
				'type'      => ($param['errcode'] == '0')?'Success':'Error',
				'content'   => ($param['content'])?$param['content']:$param['msg'],
				'title'     => ($param['errcode'] == '0')?'操作成功啦!':'操作失败啦!',
				'icon'      => ($param['errcode'] == '0')?'fa-check':'fa-remove'
			);
			$return = array_merge($return, $param);
		}else{
			$return = array(
				'type'      => 'Error',
				'content'   => '未指定的错误或未指定错误编码',
				'msg'       => '未指定的错误或未指定错误编码',
				'title'     => '操作失败啦!',
				'icon'      => 'fa-remove',
			);
		}
		return $return;
	}

	protected function defaultHeader($request='ALL'){
		header("Content-type: json; charset=utf-8");
		header('Access-Control-Allow-Origin:*');
		header('Access-Control-Allow-Headers:x-requested-with,content-type');
		switch($request){
			case 'GET':
				header('Access-Control-Allow-Methods:GET');
				return true;
			case 'POST':
				header('Access-Control-Allow-Methods:POST');
				return true;
			case 'PUT':
				header('Access-Control-Allow-Methods:PUT');
				return true;
			case 'DELECT':
				header('Access-Control-Allow-Methods:DELETE');
				return true;
			case 'ALL':
				header('Access-Control-Allow-Methods:POST, GET, PUT, DELETE');
				return true;
			default:
				return false;
		}
	}

	/**
	 * 公钥加密
	 *
	 * @param string 明文
	 * @param string 证书文件（.crt）
	 *
	 * @return string 密文（base64编码）
	 *
	 * //JS->PHP 测试
	 * $txt_en = $_POST['password'];
	 * $txt_en = base64_encode(pack("H*", $txt_en));
	 * $file = 'ssl/server.pem';
	 * $txt_de = $this->privateKeyDecode($txt_en, $file, TRUE);
	 * var_dump($txt_de);
	 * //PHP->PHP 测试
	$encrypt = $this->_publicKeyEncode('{"name":"公钥加密私钥解密测试","password":"dg123456"}');
	$decrypt = $this->_privateKeyDecode($encrypt);
	echo '<h2>公钥加密, 私钥解密</h2>';
	echo 'encode: <p>'.$encrypt.'</p><br>';
	echo 'dncode: '.$decrypt.'<br>';
	echo '<br><hr>';
	$encrypt = $this->_privateKeyEncode('{"name":"私钥加密公钥解密测试","password":"pw123456"}');
	$decrypt = $this->_publicKeyDecode($encrypt);
	echo '<h2>私钥加密, 公钥解密</h2>';
	echo 'encode: <p>'.$encrypt.'</p><br>';
	echo 'dncode: '.$decrypt.'<br>';
	echo '<br><hr>';
	 */
	private function _publicKeyEncode($sourcestr, $key, $tojs = FALSE){
		//$pubkeyid = openssl_get_publickey(file_get_contents(self::PUBLIC_KEY));
		$pubkeyid = openssl_get_publickey($key);
		$padding = $tojs?OPENSSL_NO_PADDING:OPENSSL_PKCS1_PADDING;
		if(openssl_public_encrypt($sourcestr, $crypttext, $pubkeyid, $padding)){
			return base64_encode("".$crypttext);
		}
	}

	/**
	 * 私钥加密
	 * @param $sourcestr    需加密的数据字符串
	 *
	 * @return string       加密后的字符串
	 */
	private function _privateKeyEncode($sourcestr, $key, $tojs = FALSE){
		//$prikeyid = openssl_get_privatekey(file_get_contents(self::PRIVATE_KEY));
		$prikeyid = openssl_get_privatekey($key);
		$padding = $tojs?OPENSSL_NO_PADDING:OPENSSL_PKCS1_PADDING;
		if(openssl_private_encrypt($sourcestr, $crypttext, $prikeyid, $padding)){
			return base64_encode("".$crypttext);
		}
	}

	/**
	 * 公钥解密
	 * @param string    $crypttext   需解密的字符串
	 * @param bool      $fromjs      密文是否来源于JS的RSA加密
	 *
	 * @return string|void      解密后的字符串
	 */
	private function _publicKeyDecode($crypttext, $key, $fromjs = FALSE){
		//$pubkeyid = openssl_get_publickey(file_get_contents(self::PUBLIC_KEY));
		$pubkeyid = openssl_get_publickey($key);
		$padding = $fromjs ? OPENSSL_NO_PADDING : OPENSSL_PKCS1_PADDING;
		if(openssl_public_decrypt(base64_decode($crypttext), $sourcestr, $pubkeyid, $padding)){
			return $fromjs ? rtrim(strrev($sourcestr), "/0") : "".$sourcestr;
		}
		return ;
	}

	/**
	 * 私钥解密
	 *
	 * @param string    $crypttext 密文（二进制格式且base64编码）
	 * @param bool      $fromjs    密文是否来源于JS的RSA加密
	 *
	 * @return string 明文
	 */
	private function _privateKeyDecode($crypttext, $key, $fromjs = FALSE){
		//$prikeyid = openssl_get_privatekey(file_get_contents(self::PRIVATE_KEY));
		$prikeyid = openssl_get_privatekey($key);
		$padding = $fromjs ? OPENSSL_NO_PADDING : OPENSSL_PKCS1_PADDING;
		if(openssl_private_decrypt(base64_decode($crypttext), $sourcestr, $prikeyid, $padding)){
			return $fromjs ? rtrim(strrev($sourcestr), "/0") : "".$sourcestr;
		}
		return ;
	}

	protected function _createOpensslKey(){
		if(!session('?rsa_key')){
			$config = array(
				"digest_alg" => "sha512",
				"private_key_bits" => 1024,
				"private_key_type" => OPENSSL_KEYTYPE_RSA,
			);
			$res1 = openssl_pkey_new($config);
			openssl_pkey_export($res1, $privateKeyService);
			$publicKeyService = openssl_pkey_get_details($res1);
			$res2 = openssl_pkey_new($config);
			openssl_pkey_export($res2, $privateKeyAngular);
			$publicKeyAngular = openssl_pkey_get_details($res2);
			$rsa_key = array(
				'service' => array('public' => $publicKeyAngular['key'], 'private' => $privateKeyService),
				'angular' => array('public' => $publicKeyService['key'], 'private' => $privateKeyAngular),
			);
			session('rsa_key', $rsa_key);
		}else{
			$rsa_key = session('rsa_key');
		}
		return $rsa_key;
	}

	public function test(){
		$key = $this->_createOpensslKey();
		$data = '{"op":"login","return_rsa":true,"ac":"login","mobile":"13354631875","password":"sdfhgthrtjh","rsa":true}';
		$rsa = $this->_publicKeyEncode($data, $key['service']['public']);
		echo $rsa;
		dump($key);
	}
}